package com.aisafer.fms.storage;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import com.aisafer.fms.client.dto.AuthReq;
import com.aisafer.fms.client.dto.DeleteReq;
import com.aisafer.fms.client.dto.DownReq;
import com.aisafer.fms.client.enums.StorageTypeEnums;
import com.aisafer.fms.config.AttachConfig;
import com.aisafer.fms.domain.Attachment;
import com.aisafer.fms.domain.AttachmentE;
import com.aisafer.fms.domain.Module;
import com.aisafer.fms.domain.StsConfig;
import com.aisafer.fms.enums.AttachmentStatusEnums;
import com.aisafer.fms.exception.AliyunException;
import com.aisafer.fms.exception.StorageServiceException;
import com.aisafer.fms.mapper.AttachmentEMapper;
import com.aisafer.fms.mapper.AttachmentMapper;
import com.aisafer.fms.mapper.ModuleMapper;
import com.aisafer.fms.mapper.StsConfigMapper;
import com.aisafer.fms.service.IStorageManager;
import com.aisafer.fms.service.impl.AttachmentService;
import com.aisafer.fms.service.impl.FmsPool;
import com.aisafer.fms.service.impl.PoolClient;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.ServiceException;
import com.aliyun.oss.model.OSSObject;
import com.aliyun.oss.model.PutObjectResult;

/**
 * 阿里云存储
 * 
 * @author stevin
 */
@Service("ALIYUN")
public class Aliyun extends AbstractStorage implements IStorageManager {

	private static final Logger log = LoggerFactory.getLogger(Aliyun.class);

	@Autowired
	private StsConfigMapper stsConfigDao;

	@Autowired
	private AttachConfig attachConfig;

	@Autowired
	ModuleMapper moduleMapper;

	@Autowired
	private AttachmentService attachmentService;

	@Autowired
	protected AttachmentEMapper attachmentEDao;

	@Autowired
	protected AttachmentMapper attachmentDao;

	@Override
	@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
	public void upload(AttachmentE attachmentE, byte[] content) throws StorageServiceException {
		PoolClient<OSSClient> poolClient = null;
		StsConfig stsConfig = null;
		try {
			log.info("AliyunPath:{},attachid:{}", attachmentE.getStorageKey(),attachmentE.getAttachid());
		
			if(content != null && content.length >0) {
				Attachment attachment = attachmentDao.selectByPrimaryKey(attachmentE.getAttachid());
				if (attachment == null) {
					log.error("attach {} is empty.", attachmentE.getAttachid());
					return;
				}
				Module moduleObj = moduleMapper.selectByPrimaryKey(attachment.getModuleId());
				StsConfig sts = new StsConfig();
				sts.setModuleId(moduleObj.getId());
				sts.setStorageMode(StorageTypeEnums.ALIYUN.name());
				stsConfig = stsConfigDao.select(sts);
				if (stsConfig == null || stsConfig.getId() <=0) {
					log.error("sts 配置为空 id {} ", moduleObj.getId());
					throw new ServiceException("sts 配置为空");
				}
	
				// final byte[] tempContent = getContent(content, attachParm,req);
				final String md5 = DigestUtils.md5DigestAsHex(content);
				poolClient = FmsPool.getOssPool(attachConfig).getOssClient(stsConfig);				
				PutObjectResult result = poolClient.getClient().putObject(stsConfig.getDirectory(), attachmentE.getStorageKey(),
						new ByteArrayInputStream(content));
				if (!md5.equalsIgnoreCase(result.getETag())) {
					throw new ServiceException("上传到阿里云失败:" + attachmentE.getStorageKey());
				}
				attachmentE.setTag(result.getETag());
					
			}
			attachmentService.saveAttach(attachmentE, StorageTypeEnums.ALIYUN,
					AttachmentStatusEnums.SUCCESS);
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new AliyunException(e.getMessage());
		} finally {
			if (poolClient != null) {
				FmsPool.getOssPool(attachConfig).shutdown(poolClient);
			}
		}
	}

	@Override
	public byte[] read(DownReq atte) {
		OSSObject ossObject = null;
		PoolClient<OSSClient> poolClient = null;

		try {
			Attachment attachment = attachmentDao.selectByPrimaryKey(atte.getAttachid());
			if (attachment == null) {
				return null;
			}
			Module moduleObj = moduleMapper.selectByPrimaryKey(attachment.getModuleId());
			StsConfig sts = new StsConfig();
			sts.setModuleId(moduleObj.getId());
			sts.setStorageMode(StorageTypeEnums.ALIYUN.name());
			StsConfig stsConfig = stsConfigDao.select(sts);
			if (stsConfig == null || stsConfig.getId() <= 0) {
				log.error("sts 配置为空 id {} ", moduleObj.getId());
				throw new ServiceException("sts 配置为空");
			}
			// 创建OSSClient实例
			poolClient = FmsPool.getOssPool(attachConfig).getOssClient(stsConfig);
			ossObject = poolClient.getClient().getObject(stsConfig.getDirectory(), atte.getStorageKey());
			return IOUtils.toByteArray(ossObject.getObjectContent());
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return null;
		} finally {
			if (poolClient != null) {
				FmsPool.getOssPool(attachConfig).shutdown(poolClient);
			}
		}
	}

	@Override
	public String getAuthUrl(AuthReq req) throws ServiceException {

		try {
			List<AttachmentE> attaEList = attachmentService.getAttachment(req.getAttachid(),
					StorageTypeEnums.ALIYUN.name());
			if (attaEList != null && attaEList.size() > 0) {
				AttachmentE attachmentE = attaEList.get(0);
				Attachment attachment = attachmentDao.selectByPrimaryKey(attachmentE.getAttachid());
				Module moduleObj = moduleMapper.selectByPrimaryKey(attachment.getModuleId());
				return getGennerateUrl(moduleObj, attachmentE.getStorageKey(), req);
			} else if (StringUtils.isNotEmpty(req.getModulekey())) {
				Module module = new Module();
				module.setModuleKey(req.getModulekey());
				Module moduleObj = moduleMapper.select(module);
				return getGennerateUrl(moduleObj, String.valueOf(req.getAttachid()), req);
			}

		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}

	private String getGennerateUrl(Module module, String storageKey, AuthReq req) {
		PoolClient<OSSClient> poolClient = null;
		StsConfig stsConfig = null;
		try {
			StsConfig sts = new StsConfig();
			sts.setModuleId(module.getId());
			stsConfig = stsConfigDao.select(sts);
			if (stsConfig == null || stsConfig.getId() <= 0) {
				log.error("sts 配置为空 id {} ", module.getId());
				throw new ServiceException("sts 配置为空");
			}

			poolClient = FmsPool.getOssPool(attachConfig).getOssClient(stsConfig);
			// 生成URL签名(HTTP PUT请求)
			URL signedUrl = poolClient.getClient().generatePresignedUrl(stsConfig.getDirectory(), storageKey,
					getExpirationDate(req));
			log.info("signed url for putObject: {} ", signedUrl);
			return String.valueOf(signedUrl);
		} catch (Exception e) {
			log.error(e.getMessage());
			return null;
		}finally {
			if (poolClient != null) {
				FmsPool.getOssPool(attachConfig).shutdown(poolClient);
			}
		}
	}


	private byte[] getOssObject(StsConfig stsConfig, DownReq req) {
		OSSObject ossObject = null;
		PoolClient<OSSClient> poolClient = null;

		InputStream is = null;
		try {
		// 创建OSSClient实例
		poolClient = FmsPool.getOssPool(attachConfig).getOssClient(stsConfig);
		ossObject = poolClient.getClient().getObject(stsConfig.getDirectory(), String.valueOf(req.getAttachid()));
		is = ossObject.getObjectContent();
		if (is != null) {
			try {
				return IOUtils.toByteArray(is);
			} catch (IOException e) {
				log.error(e.getMessage());
				return null;
			}finally {
				IOUtils.closeQuietly(is);
			}
		}}catch(Exception e) {
			log.error(e.getMessage());
		}finally {
			if (poolClient != null) {
				FmsPool.getOssPool(attachConfig).shutdown(poolClient);
			}
		}
		return null;
	}

	@Override
	public boolean delete(DeleteReq req) {
		PoolClient<OSSClient> poolClient = null;

		try {
			Attachment attachment = attachmentDao.selectByPrimaryKey(req.getAttachid());
			if (attachment == null) {
				return false;
			}
			Module moduleObj = moduleMapper.selectByPrimaryKey(attachment.getModuleId());
			StsConfig sts = new StsConfig();
			sts.setModuleId(moduleObj.getId());
			sts.setStorageMode(StorageTypeEnums.ALIYUN.name());
			StsConfig stsConfig = stsConfigDao.select(sts);
			if (stsConfig == null || stsConfig.getId() <= 0) {
				log.error("sts 配置为空 id {} ", moduleObj.getId());
				throw new ServiceException("sts 配置为空");
			}
			// 创建OSSClient实例
			poolClient = FmsPool.getOssPool(attachConfig).getOssClient(stsConfig);
			 poolClient.getClient().deleteObject(stsConfig.getDirectory(), req.getStorageKey());
			return true;
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			return false;
		} finally {
			if (poolClient != null) {
				FmsPool.getOssPool(attachConfig).shutdown(poolClient);
			}
		}
	}

}
